<template>
    <n-space :wrap-item="false" class="h-100" style="flex-wrap: nowrap">
        <div ref="fileTree" style="margin-right:5px;padding-right:2px;border-right:1px #ddd solid;width:250px;">
            <n-spin class="spin h-100" :show="loading" size="large">
                <n-tree class="h-100"  style="overflow: auto;"
                        block-node
                        :checkable="checkable"
                        :draggable="false"
                        :data="data"
                        :checked-keys="checkedKeys"
                        :on-load="handleLoad"
                        :expanded-keys="expandedKeys"
                        :check-strategy="checkStrategy"
                        :allow-checking-not-loaded="cascade"
                        :cascade="cascade"
                        :selectable="selectable"
                        :multiple="multiple"
                        :virtual-scroll="false"
                        expand-on-click
                        @drop="handleDrop"
                        :node-props="nodeProps"
                        @update:checked-keys="handleCheckedKeysChange"
                        @update:expanded-keys="handleExpandedKeysChange"
                />
            </n-spin>
        </div>


        <n-layout-content
            class="h-100"
            style="display: inline-block;word-break: break-all;">
            <!--<p>{{ viewPath }}</p>-->
            <!--<span v-html="JSON.stringify(viewFiles,null,4)-->
            <!--    .replace(/ {4}/g,'&emsp;')-->
            <!--    .replace(/\n/g,'<br>')">-->
            <!--</span>-->
            <FileList v-model="viewFiles"></FileList>
        </n-layout-content>
    </n-space>

</template>

<script lang="ts">
import {defineComponent, onBeforeMount, onMounted, ref, toRefs, watch} from "vue";
import {TreeDropInfo, TreeOption, useMessage} from 'naive-ui'
import FileList from "frontend/src/components/explorer/fileList.vue";
import debounce from "lodash/debounce";
import system from "frontend/src/utils/wails/system";

function getDiskList() {
    return new Promise<TreeOption[]>(resolve => {
        system.disk.GetDiskPartitions().then((disks) => {
            resolve(disks.map((item) => {
                return {
                    label: item.mountpoint + "/",
                    key: item.mountpoint + "/",
                    isLeaf: false
                }
            }))
        })
    })
}

function findSiblingsAndIndex(
    node: TreeOption,
    nodes?: TreeOption[]
): [TreeOption[], number] | [null, null] {
    if (!nodes) return [null, null]
    for (let i = 0; i < nodes.length; ++i) {
        const siblingNode = nodes[i]
        if (siblingNode.key === node.key) return [nodes, i]
        const [siblings, index] = findSiblingsAndIndex(node, siblingNode.children)
        if (siblings && index !== null) return [siblings, index]
    }
    return [null, null]
}

export default defineComponent({
    components:{
        FileList
    },
    props: {
        showFileInTree: {
            type: Boolean,
            default:() => false
        }
    },
    setup(props) {
        const {showFileInTree} = toRefs(props)
        const message = useMessage()
        const expandedKeysRef = ref<string[]>([])
        const checkedKeysRef = ref<string[]>([])
        const dataRef = ref<TreeOption[]>([])
        const viewPath = ref("")
        const viewFiles = ref<any[]>([])
        const loading = ref(true)

        onMounted(() => {
            loading.value = true
            getDiskList().then((disks) => {
                dataRef.value = disks
                loading.value = false
            })
        })

        const fileTree = ref()

        console.log(dataRef)
        watch(dataRef,(v)=>{
            console.log(v)
        })

        onMounted(()=>{
            let fileTreeDom = fileTree.value
            let x = 0
            let flag = false
            fileTreeDom.addEventListener("mousemove",(event)=>{
                let width = fileTreeDom.offsetWidth
                if(width - event.offsetX <= 5){
                    fileTreeDom.style.cursor = "e-resize"
                } else {
                    if(!flag){
                        fileTreeDom.style.cursor = "auto"
                        fileTreeDom.style.borderRight = "1px solid #ddd"
                    } else {
                        fileTreeDom.style.borderRight = "2px dashed rgb(166, 166, 166)"
                    }
                }
            })

            function mouseUp() {
                document.body.style.cursor = "auto"
                document.getElementById("app")!.style.userSelect = "auto"
                fileTreeDom.style.borderRight = "1px solid #ddd"
                x = fileTreeDom.offsetWidth
                flag = false
            }


            function mouseMove(event) {
                debounce(()=>{
                    if(flag){
                        let rect = fileTreeDom.getBoundingClientRect();
                        let offsetX = event.clientX - rect.left;
                        fileTreeDom.style.width = x + (offsetX - x) + 'px';
                        document.body.style.cursor = "e-resize"
                        fileTreeDom.style.borderRight = "2px dashed rgb(166, 166, 166)"
                    }

                    // 如果鼠标移出元素或屏幕外
                    if (fileTreeDom.offsetX <= 0 || fileTreeDom.offsetX >= document.body.clientWidth + 2) {
                        mouseUp()
                    }
                },10)()
            }

            // 阻止事件冒泡
            // 不仅仅要stopPropagation，还要preventDefault
            function pauseEvent(e){
                if(e.stopPropagation) e.stopPropagation();
                if(e.preventDefault) e.preventDefault();
                e.cancelBubble=true;
                e.returnValue=false;
                return false;
            }
            window.addEventListener("mousemove", mouseMove);
            window.addEventListener("mouseup", mouseUp);

            onBeforeMount(()=>{
                window.removeEventListener("mousemove", mouseMove);
                window.removeEventListener("mouseup", mouseUp);
            })

            fileTreeDom.addEventListener("mousedown",(event)=>{
                console.log("mousedown",event)
                let rect = event.target.getBoundingClientRect();
                let offsetX = event.clientX - rect.left;
                x = fileTreeDom.offsetWidth
                // let width = fileTreeDom.offsetWidth
                flag = x - offsetX <= 10;

                document.body.style.cursor = "e-resize"
                fileTreeDom.style.borderRight = "2px dashed rgb(166, 166, 166)"
                document.getElementById("app")!.style.userSelect = "none"
                console.log("flag",flag)
            })
        })

        return {
            loading,
            fileTree,
            showFileInTree,
            viewPath,
            viewFiles,
            checkable: ref(false),
            checkStrategy: ref<'all' | 'parent' | 'child'>('all'),
            cascade: ref(true),
            data: dataRef,
            selectable: ref(false),
            multiple: ref(false),
            expandedKeys: expandedKeysRef,
            checkedKeys: checkedKeysRef,
            nodeProps({option}: { option: TreeOption }) {
                return {
                    onClick() {
                        console.log("node click", option)
                        let path = String(option.key)
                        viewPath.value = path


                        system.disk.ScanDir(path).then(entries=>{
                            let data: TreeOption[] = []

                            for (let i = 0; i < entries.length; i++) {
                                let item = entries[i]
                                data.push({
                                    isLeaf: !item.IsDir || item.IsSymlink,
                                    key: item.Path,
                                    label: item.Name,
                                    ...item,
                                })
                            }

                            viewFiles.value = data.sort((a, b) => {
                                if (a.IsDir && b.IsDir) {
                                    return 0
                                }

                                return a.IsDir ? -1 : 1
                            })
                        })
                    }
                }
            },
            handleExpandedKeysChange(expandedKeys: string[]) {
                expandedKeysRef.value = expandedKeys
            },
            handleCheckedKeysChange(checkedKeys: string[]) {
                checkedKeysRef.value = checkedKeys
            },
            handleDrop({node, dragNode, dropPosition}: TreeDropInfo) {
                console.log("handleDrop")
                console.log(node, dragNode, dropPosition)
                const [dragNodeSiblings, dragNodeIndex] = findSiblingsAndIndex(
                    dragNode,
                    dataRef.value
                )
                if (dragNodeSiblings === null || dragNodeIndex === null) return
                dragNodeSiblings.splice(dragNodeIndex, 1)
                if (dropPosition === 'inside') {
                    if (node.children) {
                        node.children.unshift(dragNode)
                    } else {
                        node.children = [dragNode]
                    }
                } else if (dropPosition === 'before') {
                    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(
                        node,
                        dataRef.value
                    )
                    if (nodeSiblings === null || nodeIndex === null) return
                    nodeSiblings.splice(nodeIndex, 0, dragNode)
                } else if (dropPosition === 'after') {
                    const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(
                        node,
                        dataRef.value
                    )
                    if (nodeSiblings === null || nodeIndex === null) return
                    nodeSiblings.splice(nodeIndex + 1, 0, dragNode)
                }

                dataRef.value = Array.from(dataRef.value)
            },
            handleLoad(node: TreeOption) {
                return new Promise<void>((resolve) => {
                    let path = String(node.key)
                    console.log(path)

                    system.disk.ScanDir(path).then(entries=>{
                        let data: TreeOption[] = []

                        for (let i = 0; i < entries.length; i++) {
                            let item = entries[i]
                            data.push({
                                isLeaf: !item.IsDir || item.IsSymlink,
                                key: item.Path,
                                label: item.Name,
                                ...item
                            })
                        }

                        node.children = data.filter((item) => {
                            if (!showFileInTree.value) {
                                return item.IsDir
                            } else {
                                return true
                            }
                        })
                        resolve()
                    })
                })
            }
        }
    }
})
</script>

<style lang="less" scoped>
.spin {
    ::v-deep(.n-spin-content){
        height: 100%
    }
}
</style>